package dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree;


import dk.mirasola.systemtraining.bridgewidgets.shared.model.Distribution;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.Hand;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.Seat;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.Suit;

import java.util.HashSet;
import java.util.Set;

public final class FitDistributionFilter extends DistributionFilterGroupItem {
    public static final int MIN_SUITS_LENGTH = 0;
    public static final int MAX_SUITS_LENGTH = 30;

    private Set<Seat> seats = new HashSet<Seat>();
    private Set<Suit> suits = new HashSet<Suit>();
    private CompareOperator comparator = CompareOperator.EQUAL;
    private int totalCards = 8;

    /**
     * Gets the set of SEATS
     *
     * @return
     */
    public Set<Seat> getSeats() {
        return seats;
    }

    public void setSeats(Set<Seat> seats) {
        if (seats == null) {
            throw new NullPointerException();
        }
        this.seats = seats;
    }

    /**
     * Gets the set of suits
     *
     * @return
     */
    public Set<Suit> getSuits() {
        return suits;
    }

    public void setSuits(Set<Suit> suits) {
        if (seats == null) {
            throw new NullPointerException();
        }
        this.suits = suits;
    }

    /**
     * Gets comparator
     *
     * @return
     */
    public CompareOperator getComparator() {
        return comparator;
    }

    /**
     * Sets comparator
     *
     * @param comparator
     */
    public void setComparator(CompareOperator comparator) {
        this.comparator = comparator;
    }

    /**
     * Gets accumulated length
     *
     * @return
     */
    public Integer getTotalCards() {
        return totalCards;
    }

    /**
     * Sets accumulated Length
     *
     * @param totalCards - an integer between 1 and 30
     */
    public void setTotalCards(Integer totalCards) {
        if (totalCards == null) {
            throw new NullPointerException();
        }
        if (this.totalCards < MIN_SUITS_LENGTH || this.totalCards > MAX_SUITS_LENGTH) {
            throw new IllegalArgumentException("cummulatedLength must an integer between 1 and 30");
        }
        this.totalCards = totalCards;
    }

    public String toString() {
        StringBuilder text = new StringBuilder();

        // add SEATS
        for (Seat seat : seats) {
            text.append(seat).append(":");
        }
        text.append(";");

        // add suits
        for (Suit suit : suits) {
            text.append(suit).append(":");
        }
        text.append(";");

        // add comparator and suits length
        text.append(comparator).append(";").append(totalCards);

        return text.toString();
    }

    protected boolean matchesInternal(Distribution distribution) {
        if (seats.size() == 0 || suits.size() == 0)
            return true;

        int sum = 0;

        // loop over SEATS
        for (Seat seat : seats) {
            Hand hand = distribution.getHand(seat);
            // loop over suits
            for (Suit suit : suits) {
                sum += hand.getCardsCount(suit);
            }
        }

        return comparator.compare(sum, totalCards);
    }

    @Override
    public boolean isCopy(GroupItem groupItem) {
        if (!super.isCopy(groupItem)) return false;
        if (!(groupItem instanceof FitDistributionFilter)) return false;

        FitDistributionFilter that = (FitDistributionFilter) groupItem;
        return totalCards == that.totalCards && comparator == that.comparator
                && seats.equals(that.seats) && suits.equals(that.suits);
    }

    @Override
    public FitDistributionFilter copy() {
        FitDistributionFilter copy = new FitDistributionFilter();
        copy.setInverted(this.getInverted());
        copy.seats.addAll(this.seats);
        copy.suits.addAll(this.suits);
        copy.comparator = this.comparator;
        copy.totalCards = this.totalCards;
        return copy;
    }
}
